package com.share.mail;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import javax.mail.Address;
import javax.mail.FetchProfile;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.UIDFolder;
import javax.mail.Flags.Flag;

import org.springframework.stereotype.Component;

import com.share.commons.util.DateFormatUtil;
import com.share.commons.util.FileUtil;
import com.sun.mail.pop3.POP3Folder;
import com.sun.xml.internal.messaging.saaj.packaging.mime.internet.MimeUtility;

/**
 * 说明：邮件收件箱 <br/>
 * 作者：杨浩泉 <br/>
 * 日期：2009-9-6
 */
@Component
public class InBoxMailManager {
	
	/** 获得邮箱连接的地址作为存放UID文件的名称 */
	private String saveUIDFilePath ;

	
	/**
	 * 读取邮件的入口
	 * @param username 邮箱账号
	 * @param password 邮箱密码
	 * @param type 读取邮箱类型（读取所有邮件列表/打开某封邮件）取值为readList/null
	 * @param delUID 要删除的UID
	 * @param messageId 打开某封邮件
	 * @param realPath 邮件UID的保存路径
	 * @return
	 */
	public InBoxMailVo inboxMailMessage(String username,String password,String type,String delUID,int messageId,String realPath) {
		InBoxMailVo inboxvos = new InBoxMailVo() ;

		try {
			//获得MailPOP3的缺省配置信息
			MailConfiguraton config = MailConfiguraton.getInstance() ;
			
			Properties pros = System.getProperties();
			pros.setProperty("mail.pop3.host", config.getMailPOP3Host());
			pros.setProperty("mail.pop3.port", config.getMailPOP3Port());
			
			String userName = (!"".equals(username.trim()) ? username.trim() : config.getUserNameAdmin()) ;
			String passWord = (!"".equals(password.trim()) ? password.trim() : config.getPassWordAdmin()) ;
			
			//获得邮箱会话
			Session session = Session.getInstance(pros);
			//获得邮箱操作对象
			Store store = session.getStore(config.getMailPOP3Protocol());
			
			//连接邮箱
			store.connect(userName,passWord);
			
			//获得邮箱连接的地址作为存放UID文件的名称
			saveUIDFilePath = realPath+"\\mailUIDFile\\"+store.getURLName().toString().substring(store.getURLName().toString().lastIndexOf("//")+2)+".txt" ;
			
			//指定收件箱的文件夹
			POP3Folder folder = (POP3Folder) store.getFolder("INBOX");
			
			// 打开邮箱
			folder.open(Folder.READ_WRITE);
			
			Message[] msgs = folder.getMessages();
			
			FetchProfile profile = new FetchProfile();
			profile.add(UIDFolder.FetchProfileItem.UID);
			profile.add(FetchProfile.Item.ENVELOPE);
			profile.add(FetchProfile.Item.FLAGS);
			profile.add(FetchProfile.Item.CONTENT_INFO);
			folder.fetch(msgs, profile);
			
			if("readList".equals(type)) {
				
				//获得邮箱的基本信息、邮件的数量、未读、已读
				Object[] msginfo = getMsgBaseInfo(folder) ;
				
				inboxvos.setMessageCount(Integer.parseInt(msginfo[0].toString())) ;
				inboxvos.setReaderMessageCount(Integer.parseInt(msginfo[1].toString())) ;
				inboxvos.setUnReaderMessageCount(Integer.parseInt(msginfo[2].toString())) ;
				inboxvos.setReadMsgUID(msginfo[3].toString()) ;
				
				//邮件正文信息列表
				inboxvos.setMailBasicInfo(readBasicMailList(folder)) ;
				
			} else if("delMail".equals(type)) {
				inboxvos.setDelConfir(deleteMail(folder, delUID)) ;
			}else {
				inboxvos.setMailBodyInfo(readBasicMailBody(folder,messageId)) ;
			}
			folder.close(true) ;
			store.close() ;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return inboxvos ;

	}
	
	/**
	 * 删除邮件
	 * @param folder
	 */
	public boolean deleteMail(POP3Folder folder,String delUID) {
		
		try {
			Message[] msgs = (Message[])folder.getMessages() ;
			
			String[] mailsplit = delUID.split(",") ;
			
			for(int i=0; i<msgs.length; i++) {
				if(compare(folder.getUID(msgs[i]), mailsplit)) {
					
					Message msg = (Message) msgs[i] ;
					
					//给需要删除的邮件做标识
					msg.setFlag(Flag.DELETED, true) ;
				}
			}
			return true ;
		} catch (MessagingException e) {
			System.out.println("添加邮件删除标识失败....");
			e.printStackTrace();
		}
		return false ;
	}
	
	/** 获得邮箱的基本信息、邮件的数量、未读、已读 */
	public Object[] getMsgBaseInfo(POP3Folder folder) {
		Object[] msginfo = new Object[4] ;
		try {
			Message[] msgs = folder.getMessages() ;
			boolean isRecord = isRecord() ;
			
			Object[] objurmcuid = getUnReaderMail(folder,msgs,folder.getMessageCount()) ;
			
			int messageCount = folder.getMessageCount();
			int unReaderMessageCount = (isRecord == true ? messageCount : Integer.parseInt(objurmcuid[0].toString())) ;
			
			//邮件总数量
			msginfo[0] = messageCount ;
			//已读邮件数量
			msginfo[1] = messageCount - unReaderMessageCount ;
			//未读邮件数量
			msginfo[2] = unReaderMessageCount ;
			
			msginfo[3] = objurmcuid[1].toString() ;
			
		} catch (MessagingException e) {
			System.out.println("获得邮箱的基本信息出错、邮件的数量、未读、已读...");
			e.printStackTrace();
		}
		System.out.println("=================邮件收取完成=================");
		return msginfo ;
	}
	
	/** 第一次该文件不存在，全部是未读邮件，并创建txt文件，文件名为邮箱地址 */
	public boolean isRecord() {
		return FileUtil.existFile(saveUIDFilePath) ;
	}
	
	/** 打开某封邮件信息，将该封邮件的UID写到文件上，标识为已读邮件 */
	public boolean writeMailFile(String uid) {
		File file = null ;
		FileWriter fw = null ;
		BufferedWriter bw = null ;
		
		try {
			file = new File(saveUIDFilePath) ;
			fw = new FileWriter(file,true) ;
			bw = new BufferedWriter(fw) ;
			bw.write(uid+",") ;
			bw.flush() ;
			fw.flush() ;
			return true ;
		} catch (IOException e) {
			e.printStackTrace();
		} finally{
			try {
				if(null != bw)
					bw.close() ;
				if(null != fw) 
					fw.close() ;
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return false ;
	}
	
	/** 读取文件的所有UID数据，用于比较 */
	public String readMailFile() {
		String content="";
		FileReader fr = null ;
		BufferedReader br= null; 
		try {
			fr = new FileReader(saveUIDFilePath) ;
			br=new BufferedReader(fr);
			
			String line;
			while((line=br.readLine())!=null){
				content += line ;
			}
		} catch (Exception e) {
			e.printStackTrace() ;
		} finally {
			try {
				if(null != br)
					br.close() ;
				if(null != fr) 
					fr.close() ;
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return content ;
	}
	
	/**
	 * 比较当前邮件的UID与以保存到文件上的UID值，做比较，
	 * @param str 邮件的UID
	 * @param mailsplit 文件上的所有UID
	 * @return boolean值，UID存在返回true，与之相反
	 */
	public boolean compare(String str,String[] mailsplit) {
		
		for(int i=0; i<mailsplit.length; i++) {
			if(!mailsplit[i].equals("")) {
				if(mailsplit[i].equals(str)) {
					return true ;
				}
			}
		}
		return false ;
	}
	
	
	/**
	 * 获得未读邮件数量
	 * 获得邮箱上所有邮件的UID与以保存到文件上的UID进行比较，如果不存在，则unReaderCount++
	 * @param folder
	 * @param msgs
	 * @param messageCount
	 * @return 未读邮件数量，整型
	 */
	public String[] getUnReaderMail(POP3Folder folder,Message[] msgs,int messageCount) {
		String[] obj = new String[2] ;
		
		int unReaderCount = 0 ;
		
		String readMailFileUID = readMailFile() ;
		
		String[] mailsplit = readMailFileUID.split(",") ;
		try {
			for(int i=0; i<messageCount; i++) {
				if(!compare(folder.getUID(msgs[i]),mailsplit)) {
					unReaderCount ++ ;
				}
			}
			obj[0] = ""+unReaderCount ;
			obj[1] = readMailFileUID ;
		} catch (MessagingException e) {
			System.out.println("获得Message的UID出错...");
			e.printStackTrace();
		}
		return obj ;
	}

	/**
	 * 获得所有邮件的标题，以及索引
	 * @param msgs
	 * @param folder
	 * @throws MessagingException
	 * @throws IOException
	 */
	public List<InBoxMailInfo> readBasicMailList(POP3Folder folder) throws MessagingException, IOException {
		List<InBoxMailInfo> mailListInfo = new ArrayList<InBoxMailInfo>() ;
		
		Message[] msgs = folder.getMessages() ;
		for (int i = 0; i < msgs.length; i++) {
			System.out.println("current:" + folder.getUID(msgs[i]));
			InBoxMailInfo inboxinfo = new InBoxMailInfo() ;
			inboxinfo.setMessageId(i+1) ;
			inboxinfo.setMessageFrom(MimeUtility.decodeText(msgs[i].getFrom()[0].toString())) ;
			inboxinfo.setMessageSubject(msgs[i].getSubject()) ;
			inboxinfo.setMessageDate(DateFormatUtil.formatE(msgs[i].getSentDate())) ;
			inboxinfo.setMsgUID(folder.getUID(msgs[i])) ;
			
			/** 以下用于驱动模型，如果使用异步交互，可删除 */
			//如果有多个接收者，则以分号隔开
			Address[] addrTO = (msgs[i].getAllRecipients()) ;
			StringBuffer recipients = new StringBuffer();
			for(int j=0; j<addrTO.length; j++) {
				recipients.append((i == 0 ? "" : ";&nbsp;&nbsp;&nbsp;")+ addrTO[j].toString());
			}
			inboxinfo.setMessageTo(recipients.toString()) ;
			
			Part part = (Part) msgs[i];
			
			//纯文本类型
			if(part.isMimeType("text/*")) {
				inboxinfo.setMessageContent(msgs[i].getContent().toString()) ;
			}
			//复杂类型（多媒体类型）
			if(part.isMimeType("multipart/*")) {
				Multipart mp = (Multipart) part.getContent();
				
				inboxinfo.setMessageContent(mp.getBodyPart(0).getContent().toString()) ;
			}
			
			
			mailListInfo.add(inboxinfo) ;
		}
		return mailListInfo ;
	}
	
	/**
	 * 打开邮件，阅读正文
	 * 如果当前邮件的UID已存在文件上，则不想当前邮件的UID写到文件，不存在则写
	 * @param msgs
	 * @param folder
	 * @param msgId
	 * @throws MessagingException
	 * @throws IOException
	 */
	public InBoxMailInfo readBasicMailBody(POP3Folder folder,int msgId) throws MessagingException, IOException {
		msgId = msgId-1 ;
		
		Message[] msgs = folder.getMessages() ;
		
		InBoxMailInfo inboxinfo = new InBoxMailInfo() ;
		
		String uid = folder.getUID(msgs[msgId]) ;
		String[] mailsplit = readMailFile().split(",") ;
		if(!compare(uid,mailsplit)) {
			//将打开邮件的UID写到文件上
			writeMailFile(uid);
		}
		
		Part part = (Part) msgs[msgId];
		
		//如果有多个接收者，则以分号隔开
		Address[] addrTO = (msgs[msgId].getAllRecipients()) ;
		StringBuffer recipients = new StringBuffer();
		for(int i=0; i<addrTO.length; i++) {
			recipients.append((i == 0 ? "" : ";&nbsp;&nbsp;&nbsp;")+ addrTO[i].toString());
		}
		
		inboxinfo.setMessageId(msgId) ;
		inboxinfo.setMessageFrom(MimeUtility.decodeText(msgs[msgId].getFrom()[0].toString())) ;
		inboxinfo.setMessageTo(recipients.toString()) ;
		inboxinfo.setMessageSubject(msgs[msgId].getSubject()) ;
		inboxinfo.setMessageDate(DateFormatUtil.formatE(msgs[msgId].getSentDate()) + " ("+DateFormatUtil.getWeek(msgs[msgId].getSentDate())+")") ;
		
		//纯文本类型
		if(part.isMimeType("text/*")) {
			inboxinfo.setMessageContent(msgs[msgId].getContent().toString()) ;
			
		}
		//复杂类型（多媒体类型）
		if(part.isMimeType("multipart/*")) {
			Multipart mp = (Multipart) part.getContent();
			
			inboxinfo.setMessageContent(mp.getBodyPart(0).getContent().toString()) ;
		}
		
		return inboxinfo ;
	}

	public static void main(String[] args) {
		String path = "E:/Tomcat/share-tomcat-6.0.18/webapps/share" ;

		//获得所有邮件的基本信息
		/*InBoxMailVo ibm = new InBoxMailManager().inboxMailMessage("serup_server","serup_server123","readList",0,path) ; 
		System.out.println("***************邮件列表***************");
		System.out.print("邮件总数量[" + ibm.getMessageCount()+"]");
		System.out.print("已读邮件[" + ibm.getReaderMessageCount()+"]");
		System.out.print("未读邮件[" + ibm.getUnReaderMessageCount()+"]");
		
		System.out.println("\n");
		
		String[] ruid = ibm.getReadMsgUID().split(",") ;
		
		for (Iterator<InBoxMailInfo> iterator = ibm.getMailBasicInfo().iterator(); iterator.hasNext();) {
			InBoxMailInfo ibminfo = (InBoxMailInfo) iterator.next();
			//System.out.print("[来至]"+ibminfo.getMessageFrom() + "  ");
			System.out.print("[标题]"+ibminfo.getMessageSubject() + "  ");
			//System.out.print("[日期]"+ibminfo.getMessageDate() + "  ");
			System.out.print("[索引]"+ibminfo.getMessageId() + "  ");
			System.out.print("[UID]"+ibminfo.getMsgUID() + "  ");
			for(int ia = 0; ia<ruid.length; ia++) {
				if(ibminfo.getMsgUID().equals(ruid[ia])) {
					System.out.print("【已读】");
				}
			}
			System.out.println("[[[["+ibminfo.getMessageContent());
			System.out.println("");
		}
		
		System.out.println("");*/
		
		System.out.println("***************打开某封邮件***************\n");
		
		//阅读某封邮箱
		InBoxMailVo ibmbody = new InBoxMailManager().inboxMailMessage("serup_server","serup_server123",null,null,4,path) ; 
		
		InBoxMailInfo ibmi = ibmbody.getMailBodyInfo() ;
		
		
		System.out.print("[来至]"+ibmi.getMessageFrom() + "  ");
		System.out.print("[标题]"+ibmi.getMessageSubject() + "  ");
		System.out.print("[日期]"+ibmi.getMessageDate() + "  ");
		System.out.println("[索引]"+ibmi.getMessageId());
		//System.out.println(ibmi.getMessageContent());
		
	}
}

